
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, simpledialog
import json
import time
import random
import requests
# import os #不再需要 os 和 dotenv

# --- 全局配置与常量 ---
# 直接将 API 凭证硬编码到代码中
# 【【【警告：非常不建议在生产环境中这样做，仅用于快速测试或个人项目！】】】
# 【【【请替换为你的实际凭证】】】
WENXIN_APP_ID = "-----"  # 替换为你的 App ID
WENXIN_SECRET_KEY = "----" # 替换为你的 Secret Key
WENXIN_USER_OPEN_ID = "pokemon_user_001" # 可以是任意固定字符串，代表你的应用用户

# 检查凭证是否已填写 (一个简单的运行时提醒)
if WENXIN_APP_ID == "YOUR_APP_ID_HERE" or WENXIN_SECRET_KEY == "YOUR_SECRET_KEY_HERE":
    print("*" * 60)
    print("警告：文心千帆 API 凭证尚未在代码中正确配置！")
    print("请在 pokemon_game_simplified_no_env_no_prompt.py 文件中")
    print("找到 WENXIN_APP_ID 和 WENXIN_SECRET_KEY 并替换为你的实际凭证。")
    print("*" * 60)
    # 你可以在这里决定是退出程序还是允许继续（但API调用会失败）
    # exit() # 如果希望强制退出

# 升级相关常量
BASE_HP_PER_LEVEL = 10
INITIAL_BASE_HP = 20
BASE_STAT_INCREASE_PER_LEVEL = 1
BONUS_PER_POTENTIAL_POINT = 1 
POTENTIAL_MIN = 1
POTENTIAL_MAX = 3
STAT_KEYS = ["attack", "defense", "special_attack", "special_defense", "speed"]


# --- 简化版宝可梦和技能类 ---
class MoveSimplified:
    def __init__(self, name, type, power, category, accuracy, pp):
        self.name = name
        self.type = type
        self.power = int(power)
        self.category = category
        self.accuracy = int(accuracy)
        self.pp = int(pp)
        self.current_pp = int(pp)

    def to_dict(self):
        return {
            "name": self.name,
            "type": self.type,
            "power": self.power,
            "category": self.category,
            "accuracy": self.accuracy,
            "pp": self.current_pp
        }

    @classmethod
    def from_dict(cls, data):
        return cls(**data)

class PokemonSimplified:
    def __init__(self, name, types, level=1, current_hp=None, 
                 initial_stats=None,
                 moves_data=None, xp=0, potential=None, is_wild=False):
        self.name = name
        self.types = types if isinstance(types, list) else [types]
        self.level = int(level)
        self.xp = int(xp)
        self.next_level_xp = self._calculate_next_level_xp()
        self.is_wild = is_wild

        if potential is None:
            self.potential = {key: random.randint(POTENTIAL_MIN, POTENTIAL_MAX) for key in STAT_KEYS + ["hp"]}
        else:
            self.potential = potential

        if initial_stats is None:
            self._initial_stats = {key: 10 for key in STAT_KEYS} 
        else:
            self._initial_stats = initial_stats

        self.stats = self._calculate_current_stats()
        self.max_hp = self._calculate_max_hp()
        
        self.current_hp = int(current_hp) if current_hp is not None else self.max_hp
        self.current_hp = min(self.current_hp, self.max_hp)

        self.moves = []
        if moves_data:
            for move_info in moves_data:
                self.moves.append(MoveSimplified.from_dict(move_info))
        else: # 至少给一个默认技能
            self.moves.append(MoveSimplified("撞击", "一般", 40, "物理", 100, 35))


    def _calculate_max_hp(self):
        hp_potential_bonus = (self.potential['hp'] - POTENTIAL_MIN) * BONUS_PER_POTENTIAL_POINT 
        return INITIAL_BASE_HP + (BASE_HP_PER_LEVEL + hp_potential_bonus) * (self.level -1)

    def _calculate_current_stats(self):
        current_stats = {}
        for key in STAT_KEYS:
            potential_bonus_per_level = (self.potential[key] - POTENTIAL_MIN) * BONUS_PER_POTENTIAL_POINT
            stat_val = self._initial_stats[key] + (BASE_STAT_INCREASE_PER_LEVEL + potential_bonus_per_level) * (self.level - 1)
            current_stats[key] = stat_val
        return current_stats

    def _calculate_next_level_xp(self):
        return int((self.level ** 2.8) * 8) if self.level < 100 else float('inf')

    def update_after_level_up(self):
        old_max_hp = self.max_hp
        self.stats = self._calculate_current_stats()
        self.max_hp = self._calculate_max_hp()
        hp_increase = self.max_hp - old_max_hp
        self.current_hp += hp_increase
        self.current_hp = min(self.current_hp, self.max_hp)
        return self.stats, old_max_hp, self.max_hp

    def gain_xp(self, amount):
        if self.level >= 100:
            return f"{self.name} 已经满级了！"
        self.xp += int(amount)
        log_message = f"{self.name} 获得了 {int(amount)}点经验！"
        leveled_up_messages = []
        while self.xp >= self.next_level_xp and self.level < 100:
            self.level += 1
            old_stats_display = {k:v for k,v in self.stats.items()}
            new_stats, old_hp, new_hp = self.update_after_level_up()
            level_up_msg = f"\n{self.name} 升级到了 {self.level}级！"
            level_up_msg += f"\n  最大HP: {old_hp} -> {new_hp}"
            for key in STAT_KEYS:
                level_up_msg += f"\n  {key.replace('_',' ').capitalize()}: {old_stats_display[key]} -> {new_stats[key]}"
            leveled_up_messages.append(level_up_msg)
            self.xp -= self.next_level_xp
            self.next_level_xp = self._calculate_next_level_xp()
        if leveled_up_messages:
            log_message += "".join(leveled_up_messages)
        return log_message

    def restore_pp(self):
        for move in self.moves: move.current_pp = move.pp
    
    def full_heal(self):
        self.current_hp = self.max_hp
        self.restore_pp()

    def to_dict_for_llm(self):
        # 这个字典将作为 "问题" (message.content.value.showText) 的一部分发送给LLM
        # LLM的系统提示词已在服务商端配置，它应该知道如何解读这个JSON结构
        return {
            "pokemon1": self.to_individual_pokemon_dict(), # 我方宝可梦数据
            # "pokemon2" 会在调用时由对方宝可梦填充
        }
    
    def to_individual_pokemon_dict(self): # 辅助方法，用于生成单个宝可梦的字典
        return {
            "name": self.name,
            "types": self.types,
            "level": self.level,
            "current_hp": self.current_hp,
            "max_hp": self.max_hp,
            "attack": self.stats["attack"],
            "defense": self.stats["defense"],
            "special_attack": self.stats["special_attack"],
            "special_defense": self.stats["special_defense"],
            "speed": self.stats["speed"],
            "moves": [move.to_dict() for move in self.moves]
        }

    def __str__(self):
        return f"{self.name} (Lv.{self.level}) HP: {self.current_hp}/{self.max_hp}"

# --- 文心API 调用 (已简化，不再包含系统提示词) ---
def call_wenxin_api_with_battle_data(battle_data_json_str):
    if WENXIN_APP_ID == "YOUR_APP_ID_HERE" or WENXIN_SECRET_KEY == "YOUR_SECRET_KEY_HERE":
        print("错误：API凭证未在代码中正确配置。")
        return None, "API配置错误: 凭证未在代码中设置"

    url = f"https://agentapi.baidu.com/assistant/getAnswer?appId={WENXIN_APP_ID}&secretKey={WENXIN_SECRET_KEY}"
    
    headers = {"Content-Type": "application/json"}
    payload = {
        "message": {"content": {"type": "text", "value": {"showText": battle_data_json_str}}},
        "source": WENXIN_APP_ID, 
        "from": "openapi",
        "openId": WENXIN_USER_OPEN_ID
    }
    
    # --- 打印发送给API的输入信息 (这部分保持不变) ---
    print("\n" + "="*20 + " 发送给文心API的请求 " + "="*20)
    print(f"请求URL: {url}")
    print(f"请求体 (Payload):\n{json.dumps(payload, ensure_ascii=False, indent=2)}")
    print("实际发送给大模型 (message.content.value.showText) 的内容:")
    try:
        parsed_battle_data = json.loads(battle_data_json_str)
        print(json.dumps(parsed_battle_data, ensure_ascii=False, indent=2))
    except json.JSONDecodeError:
        print(battle_data_json_str)
    print("="*60 + "\n")
    # --- 结束打印发送信息 ---

    try:
        response = requests.post(
            url, headers=headers, data=json.dumps(payload, ensure_ascii=False).encode('utf-8'), timeout=180
        )
        
        # --- 打印从API接收到的原始响应信息 (这部分保持不变) ---
        print("\n" + "="*20 + " 从文心API接收到的响应 " + "="*20)
        print(f"响应状态码: {response.status_code}")
        print("响应头 (部分):")
        for key, value in list(response.headers.items())[:5]:
            print(f"  {key}: {value}")
        response_text = response.text
        print(f"原始响应体 (Raw Text):\n{response_text}")
        print("="*60 + "\n")
        # --- 结束打印接收信息 ---

        response.raise_for_status() 
        
        result_dict = response.json()
        
        # 1. 检查顶层状态 (根据新的日志，status: 0 表示成功)
        api_status_code = result_dict.get("status") 
        
        if api_status_code != 0: # 0 表示成功
            error_message_from_api = result_dict.get("message", "未知API业务错误")
            logid = result_dict.get("logid", "N/A")
            error_full_message = f"API业务失败。状态码: {api_status_code}, 消息: {error_message_from_api}, LogID: {logid}"
            print(f"错误：{error_full_message}")
            return None, error_full_message

        # 2. 提取大模型的输出 (战斗结果JSON字符串)
        #    路径: result_dict['data']['content'][0]['data']
        answer_content = None
        try:
            data_obj = result_dict.get('data')
            if not isinstance(data_obj, dict):
                print("错误：API响应中 'data' 对象不存在或类型错误")
                return None, "API响应中 'data' 对象不存在或类型错误"

            content_list = data_obj.get('content')
            if not content_list or not isinstance(content_list, list) or len(content_list) == 0:
                print("错误：API响应中 'data.content' 列表为空或不存在")
                return None, "API响应中 'data.content' 列表为空或不存在"

            first_content_item = content_list[0]
            if not isinstance(first_content_item, dict): #  dataType: "txt"
                print("错误：API响应中 'data.content[0]' 不是预期的字典类型")
                return None, "API响应中 'data.content[0]' 不是预期的字典类型"
            
            # 'data' 字段包含了被Markdown代码块包裹的JSON字符串
            answer_content_value_markdown = first_content_item.get('data')
            
            if answer_content_value_markdown is None:
                 print("错误：API响应中 'data.content[0].data' 不存在或为null")
                 return None, "API响应中 'data.content[0].data' 不存在或为null"
            if not isinstance(answer_content_value_markdown, str):
                 print(f"错误：API响应中 'data.content[0].data' 不是字符串类型，而是 {type(answer_content_value_markdown)}")
                 return None, f"API响应中 'data.content[0].data' 不是字符串类型，而是 {type(answer_content_value_markdown)}"
            
            answer_content = answer_content_value_markdown # 此时 answer_content 是 "```json\n{...}\n```"

        except (KeyError, IndexError, TypeError) as e:
            print(f"错误：解析API响应时发生错误: {e}")
            return None, f"API响应格式路径解析错误: {e}"
        
        if not answer_content: 
            print("错误：API响应中 'data.content[0].data' 内容为空字符串")
            return None, "API响应中 'data.content[0].data' 内容为空字符串"

        # 3. 从Markdown代码块提取并解析JSON
        battle_result_json = None
        if answer_content.startswith("```json") and answer_content.endswith("```"):
            try:
                # 提取 ```json 和 ```之间的内容
                # split('```json\n', 1) 会得到 ['', '{...}\n```']
                # 或者 split('```json', 1) 后取 [1]，再 split('```', 1) 取 [0]
                json_str_cleaned = answer_content.split("```json", 1)[1].rsplit("```", 1)[0].strip()
                battle_result_json = json.loads(json_str_cleaned)
                # print(f"DEBUG: 成功从Markdown提取并解析JSON: {json.dumps(battle_result_json, ensure_ascii=False, indent=2)}")
            except (IndexError, json.JSONDecodeError) as extraction_error:
                print(f"错误：从Markdown代码块提取或解析JSON失败: {extraction_error}")
                print(f"原始Markdown内容: {answer_content}")
                return None, f"从Markdown提取JSON失败: {answer_content[:250]}"
        else:
            # 如果不是预期的Markdown格式，尝试直接解析 (可能性较小，但作为备选)
            try:
                battle_result_json = json.loads(answer_content)
                # print("DEBUG: 直接解析answer_content为JSON成功 (非Markdown)。")
            except json.JSONDecodeError:
                print(f"错误：LLM返回内容既非标准Markdown JSON也非纯JSON: {answer_content[:250]}")
                return None, f"LLM返回内容非预期格式: {answer_content[:250]}"

        if battle_result_json:
            return battle_result_json, None
        else: # 如果 battle_result_json 仍然是 None
            print("错误：未能成功从API响应中解析出战斗结果JSON。")
            return None, "未能从API响应中解析战斗结果JSON"


    except requests.exceptions.Timeout:
        print("错误：网络超时。")
        return None, "网络超时错误"
    except requests.exceptions.HTTPError as http_err: 
        error_body = ""
        try: error_body = http_err.response.json()
        except json.JSONDecodeError: error_body = http_err.response.text
        print(f"错误：HTTP网络错误: {http_err.response.status_code} - {error_body}")
        return None, f"HTTP网络错误: {http_err.response.status_code} - {error_body}"
    except requests.exceptions.RequestException as e:
        print(f"错误：网络连接错误: {str(e)}")
        return None, f"网络连接错误: {str(e)}"
    except Exception as e: 
        print(f"错误：调用API时发生未知错误: {str(e)}")
        import traceback
        traceback.print_exc()
        return None, f"调用API时发生未知错误: {str(e)}"

def get_battle_outcome_from_llm_simplified(pokemon1_obj, pokemon2_obj):
    # 构建只包含对战双方数据的JSON
    battle_data_for_llm = {
        "pokemon1": pokemon1_obj.to_individual_pokemon_dict(),
        "pokemon2": pokemon2_obj.to_individual_pokemon_dict()
    }
    battle_data_json_str = json.dumps(battle_data_for_llm, ensure_ascii=False, indent=2)
    
    # print(f"DEBUG: Battle data being sent to LLM: {battle_data_json_str}")

    result_json, error = call_wenxin_api_with_battle_data(battle_data_json_str)
    
    if error: return None, error
    if not result_json: return None, "LLM返回了空结果"

    expected_keys = {"winner", "battle_log", "pokemon1_final_hp", "pokemon2_final_hp"}
    if not isinstance(result_json, dict) or not expected_keys.issubset(result_json.keys()):
        return None, f"LLM返回的JSON结构错误或缺少键: {str(result_json)[:200]}"
    
    try:
        result_json["pokemon1_final_hp"] = max(0, int(result_json["pokemon1_final_hp"]))
        result_json["pokemon2_final_hp"] = max(0, int(result_json["pokemon2_final_hp"]))
    except ValueError:
        return None, "LLM返回的HP值无法转换为整数"

    return result_json, None

# --- 玩家类 ---
class PlayerSimplified:
    def __init__(self, name="训练家"):
        self.name = name
        self.pokemons = []
        self.money = 1000
        self.current_pokemon_index = 0

    def add_pokemon(self, pokemon_instance):
        if len(self.pokemons) < 6:
            self.pokemons.append(pokemon_instance)
            return True, f"{pokemon_instance.name} 已加入队伍！"
        return False, "队伍已满（最多6只）！"

    def get_current_pokemon(self):
        if not self.pokemons or not (0 <= self.current_pokemon_index < len(self.pokemons)):
            first_healthy_idx = self.get_next_healthy_pokemon_index()
            if first_healthy_idx != -1:
                self.current_pokemon_index = first_healthy_idx
                return self.pokemons[self.current_pokemon_index]
            return None
        return self.pokemons[self.current_pokemon_index]
    
    def get_next_healthy_pokemon_index(self, start_index=0):
        for i in range(len(self.pokemons)):
            idx = (start_index + i) % len(self.pokemons)
            if self.pokemons[idx].current_hp > 0:
                return idx
        return -1

    def switch_pokemon(self, index):
        if 0 <= index < len(self.pokemons):
            if self.pokemons[index].current_hp > 0:
                self.current_pokemon_index = index
                return True, f"去吧！{self.pokemons[index].name}！"
            return False, f"{self.pokemons[index].name} 已经没有体力了！"
        return False, "无效的宝可梦选择。"

    def has_conscious_pokemon(self):
        return any(p.current_hp > 0 for p in self.pokemons)

    def heal_all_pokemons(self):
        for pkm in self.pokemons: pkm.full_heal()

# --- 核心游戏逻辑函数 ---
def handle_battle_end_simplified(player, player_pkm, opponent_pkm_name, opponent_pkm_level, winner, battle_type="wild"):
    messages = []
    if winner == "pokemon1":
        messages.append(f"{player_pkm.name} 战胜了 {opponent_pkm_name}!")
        xp_gained = opponent_pkm_level * 12 
        xp_log = player_pkm.gain_xp(xp_gained)
        messages.append(xp_log)
        if battle_type == "trainer": 
            money_gained = opponent_pkm_level * 75
            player.money += money_gained
            messages.append(f"你获得了 ${money_gained}!")
    elif winner == "pokemon2":
        messages.append(f"{player_pkm.name} 被 {opponent_pkm_name} 打败了...")
        if not player.has_conscious_pokemon():
            messages.append("你所有的宝可梦都失去了战斗能力！眼前一片漆黑...")
            if battle_type == "trainer":
                money_lost = player.money // 15
                player.money = max(0, player.money - money_lost)
                messages.append(f"你失去了 ${money_lost}...")
        else:
            messages.append("你需要更换宝可梦！")
    else: # draw
        messages.append(f"与 {opponent_pkm_name} 的战斗以平局结束！")
        if player_pkm.current_hp <= 0 and not player.has_conscious_pokemon():
             messages.append("你所有的宝可梦都失去了战斗能力！")
    return messages

def capture_pokemon_simplified(player, defeated_pokemon_obj): 
    capture_chance = 0.4 
    if random.random() < capture_chance:
        defeated_pokemon_obj.is_wild = False 
        defeated_pokemon_obj.full_heal()    
        success, msg = player.add_pokemon(defeated_pokemon_obj)
        if success:
            return f"成功抓获了 {defeated_pokemon_obj.name}!"
        else: 
            defeated_pokemon_obj.is_wild = True 
            return f"尝试抓获 {defeated_pokemon_obj.name}, 但{msg[msg.find('队伍'):]}" 
    return f"{defeated_pokemon_obj.name} 从精灵球里逃脱了！"

def absorb_pokemon_simplified(player_pokemon, defeated_pokemon_obj):
    messages = []
    choice = random.choice(["potential", "skill"])

    if choice == "potential":
        stat_key_to_absorb = random.choice(list(player_pokemon.potential.keys()))
        old_potential = player_pokemon.potential[stat_key_to_absorb]
        new_potential = defeated_pokemon_obj.potential[stat_key_to_absorb]
        if old_potential == new_potential:
            messages.append(f"{player_pokemon.name} 尝试吸收潜力，但 {stat_key_to_absorb} 潜力值相同 ({new_potential})。")
        else:
            player_pokemon.potential[stat_key_to_absorb] = new_potential
            messages.append(f"{player_pokemon.name} 的 {stat_key_to_absorb} 潜力从 {old_potential} 替换为 {new_potential} (来自 {defeated_pokemon_obj.name})!")
            if stat_key_to_absorb == 'hp':
                player_pokemon.max_hp = player_pokemon._calculate_max_hp()
                player_pokemon.current_hp = min(player_pokemon.current_hp, player_pokemon.max_hp)
            else: 
                player_pokemon.stats = player_pokemon._calculate_current_stats()
    elif choice == "skill":
        if not defeated_pokemon_obj.moves:
            return [f"{defeated_pokemon_obj.name} 没有任何技能可以吸收。"]
        learnable_moves = [m for m in defeated_pokemon_obj.moves if m.name not in [pm.name for pm in player_pokemon.moves]]
        if not learnable_moves:
            return [f"{player_pokemon.name} 已经学会了 {defeated_pokemon_obj.name} 的所有技能，或对方没有可学技能。"]
        move_to_learn_obj = random.choice(learnable_moves)
        if len(player_pokemon.moves) < 4:
            player_pokemon.moves.append(move_to_learn_obj)
            messages.append(f"{player_pokemon.name} 学会了新技能: {move_to_learn_obj.name}!")
        else:
            idx_to_forget = random.randrange(len(player_pokemon.moves))
            forgotten_move = player_pokemon.moves[idx_to_forget]
            player_pokemon.moves[idx_to_forget] = move_to_learn_obj
            messages.append(f"{player_pokemon.name} 忘记了 {forgotten_move.name} 并学会了 {move_to_learn_obj.name}!")
    return messages

# --- Tkinter GUI (与上一版基本相同, 细节微调) ---
class PokemonGameGUISimplified:
    def __init__(self, root_window):
        self.root = root_window
        self.root.title("宝可梦收集对战 (LLM版 - 无本地Prompt)")
        self.root.geometry("700x800")

        self.player = PlayerSimplified("训练家")
        self._create_initial_player_pokemon()
        
        self.current_opponent_obj = None
        self.battle_type = "wild" 

        self._setup_main_frame()
        self._setup_battle_frame()
        
        self.switch_to_main_view_gui()

    def _create_initial_player_pokemon(self):
        pkm1 = PokemonSimplified(
            name="初始伙伴A", types=["一般"], level=3,
            initial_stats={"attack":12, "defense":10, "special_attack":10, "special_defense":10, "speed":11},
            moves_data=[
                {"name": "撞击", "type": "一般", "power": 40, "category": "物理", "accuracy": 100, "pp": 35},
                {"name": "叫声", "type": "一般", "power": 0, "category": "变化", "accuracy": 100, "pp": 40}
            ]
        )
        self.player.add_pokemon(pkm1)
        pkm2 = PokemonSimplified(
            name="初始伙伴B", types=["水"], level=3,
            initial_stats={"attack":10, "defense":11, "special_attack":12, "special_defense":10, "speed":10},
            moves_data=[
                {"name": "水枪", "type": "水", "power": 40, "category": "特殊", "accuracy": 100, "pp": 25},
            ]
        )
        self.player.add_pokemon(pkm2)

    def _setup_main_frame(self):
        self.main_frame = ttk.Frame(self.root, padding="10")
        ttk.Label(self.main_frame, text="宝可梦世界 (LLM驱动)", font=("Arial", 18, "bold")).pack(pady=15)
        
        self.player_info_display = scrolledtext.ScrolledText(self.main_frame, height=8, width=70, wrap=tk.WORD, relief=tk.GROOVE, borderwidth=2)
        self.player_info_display.pack(pady=10, fill=tk.X)
        self.player_info_display.config(state=tk.DISABLED)

        button_frame = ttk.Frame(self.main_frame)
        button_frame.pack(fill=tk.X, pady=5)
        ttk.Button(button_frame, text="创建新宝可梦", command=self._prompt_create_pokemon_gui, width=20).pack(side=tk.LEFT, padx=5, expand=True)
        ttk.Button(button_frame, text="遭遇野生宝可梦", command=self._find_wild_pokemon_gui, width=20).pack(side=tk.LEFT, padx=5, expand=True)
        
        button_frame2 = ttk.Frame(self.main_frame)
        button_frame2.pack(fill=tk.X, pady=5)
        ttk.Button(button_frame2, text="查看我的宝可梦", command=self._show_my_pokemons_gui, width=20).pack(side=tk.LEFT, padx=5, expand=True)
        ttk.Button(button_frame2, text="治疗所有宝可梦", command=self._heal_all_gui, width=20).pack(side=tk.LEFT, padx=5, expand=True)
        
        ttk.Button(self.main_frame, text="退出游戏", command=self.root.quit, width=15).pack(pady=20)

    def _setup_battle_frame(self):
        self.battle_frame = ttk.Frame(self.root, padding="10")
        self.battle_status_label = ttk.Label(self.battle_frame, text="战斗开始！", font=("Arial", 16, "bold"))
        self.battle_status_label.pack(pady=10)

        info_frame = ttk.Frame(self.battle_frame)
        info_frame.pack(fill=tk.X, pady=5)
        self.player_pokemon_label_battle = ttk.Label(info_frame, text="我方:", font=("Arial", 11))
        self.player_pokemon_label_battle.pack(side=tk.LEFT, padx=10, expand=True, fill=tk.X)
        self.opponent_pokemon_label_battle = ttk.Label(info_frame, text="对手:", font=("Arial", 11))
        self.battle_log_text = scrolledtext.ScrolledText(self.battle_frame, width=80, height=22, wrap=tk.WORD, relief=tk.SUNKEN, borderwidth=2)
        self.battle_log_text.pack(pady=10, expand=True, fill=tk.BOTH)
        self.battle_log_text.config(state=tk.DISABLED)
        
        self.action_buttons_frame_battle = ttk.Frame(self.battle_frame)
        self.action_buttons_frame_battle.pack(pady=10, fill=tk.X)

        self.proceed_button = ttk.Button(self.action_buttons_frame_battle, text="开始战斗回合", command=self._process_battle_turn_gui)
        self.switch_pokemon_button = ttk.Button(self.action_buttons_frame_battle, text="更换宝可梦", command=self._prompt_switch_pokemon_gui)
        
        self.back_to_main_button_battle = ttk.Button(self.battle_frame, text="返回主菜单", command=self._end_battle_and_return_to_main_gui)


    def _update_player_info_display_gui(self):
        self.player_info_display.config(state=tk.NORMAL)
        self.player_info_display.delete(1.0, tk.END)
        
        info = f"训练家: {self.player.name} | 金钱: ${self.player.money}\n"
        info += "当前出战: "
        current_pkm = self.player.get_current_pokemon()
        if current_pkm:
            info += f"{current_pkm.name} (Lv.{current_pkm.level}) HP: {current_pkm.current_hp}/{current_pkm.max_hp}\n"
        else:
            info += "(无宝可梦出战)\n"
        
        info += "队伍 (" + str(len(self.player.pokemons)) + "/6):\n"
        if not self.player.pokemons:
            info += "  (空)\n"
        else:
            for i, pkm in enumerate(self.player.pokemons):
                is_current_char = "*" if pkm == current_pkm else " "
                info += f" {is_current_char}{i+1}. {pkm.name} (Lv.{pkm.level}) HP: {pkm.current_hp}/{pkm.max_hp} | 类型: {', '.join(pkm.types)}\n"
        
        self.player_info_display.insert(tk.END, info)
        self.player_info_display.config(state=tk.DISABLED)

    def switch_to_main_view_gui(self):
        self.battle_frame.pack_forget()
        self.main_frame.pack(expand=True, fill=tk.BOTH)
        self._update_player_info_display_gui()

    def switch_to_battle_view_gui(self):
        self.main_frame.pack_forget()
        self.battle_frame.pack(expand=True, fill=tk.BOTH)
        self._clear_and_pack_battle_buttons([self.proceed_button, self.switch_pokemon_button])
        self.back_to_main_button_battle.pack_forget()


    def _add_battle_log_message_gui(self, message, delay=40):
        self.battle_log_text.config(state=tk.NORMAL)
        self.battle_log_text.insert(tk.END, message + "\n")
        self.battle_log_text.see(tk.END)
        self.battle_log_text.config(state=tk.DISABLED)
        self.root.update_idletasks()
        if delay > 0 and self.root.winfo_exists(): 
            time.sleep(delay / 1000.0)
            
    def _update_battle_labels_gui(self):
        player_pkm = self.player.get_current_pokemon()
        self.player_pokemon_label_battle.config(text=f"我方: {player_pkm}" if player_pkm else "我方: (无)")
        self.opponent_pokemon_label_battle.config(text=f"对手: {self.current_opponent_obj}" if self.current_opponent_obj else "对手: (无)")

    def _prompt_create_pokemon_gui(self):
        if len(self.player.pokemons) >= 6:
            messagebox.showinfo("提示", "你的队伍已满！")
            return

        top = tk.Toplevel(self.root)
        top.title("创建新宝可梦")
        top.geometry("450x600")
        top.transient(self.root)
        top.grab_set()

        fields = {}
        ttk.Label(top, text="名称:").grid(row=0, column=0, padx=5, pady=2, sticky="w")
        fields['name'] = ttk.Entry(top, width=30); fields['name'].grid(row=0, column=1, columnspan=3, padx=5, pady=2, sticky="ew")
        fields['name'].insert(0, f"伙伴{random.randint(1,100)}")

        ttk.Label(top, text="类型 (逗号分隔):").grid(row=1, column=0, padx=5, pady=2, sticky="w")
        fields['types'] = ttk.Entry(top, width=30); fields['types'].grid(row=1, column=1, columnspan=3, padx=5, pady=2, sticky="ew")
        fields['types'].insert(0, random.choice(["火", "水", "草", "电", "一般", "格斗"]))

        ttk.Label(top, text="初始等级:").grid(row=2, column=0, padx=5, pady=2, sticky="w")
        fields['level'] = ttk.Entry(top, width=5); fields['level'].grid(row=2, column=1, padx=5, pady=2, sticky="w")
        fields['level'].insert(0, "1")
        
        ttk.Label(top, text="--- 1级时属性 ---").grid(row=3, columnspan=4, padx=5, pady=5)
        stat_row = 4
        fields['initial_stats'] = {}
        for i, stat_key in enumerate(STAT_KEYS):
            ttk.Label(top, text=f"{stat_key.replace('_',' ').capitalize()}:").grid(row=stat_row + i//2, column=(i%2)*2, padx=5, pady=2, sticky="w")
            fields['initial_stats'][stat_key] = ttk.Entry(top, width=5)
            fields['initial_stats'][stat_key].grid(row=stat_row + i//2, column=(i%2)*2 + 1, padx=5, pady=2, sticky="w")
            fields['initial_stats'][stat_key].insert(0, str(random.randint(8,12)))

        ttk.Label(top, text="--- 技能 (最多4个) ---").grid(row=stat_row + (len(STAT_KEYS)+1)//2, columnspan=4, padx=5, pady=8)
        
        fields['moves_data'] = []
        move_start_row = stat_row + (len(STAT_KEYS)+1)//2 + 1
        for i in range(4):
            move_frame = ttk.LabelFrame(top, text=f"技能 {i+1}")
            move_frame.grid(row=move_start_row + i, columnspan=4, padx=5, pady=3, sticky="ew")
            
            m_fields = {}
            ttk.Label(move_frame, text="名:").pack(side=tk.LEFT, padx=2)
            m_fields['name'] = ttk.Entry(move_frame, width=8); m_fields['name'].pack(side=tk.LEFT, padx=2)
            ttk.Label(move_frame, text="类:").pack(side=tk.LEFT, padx=2) 
            m_fields['type'] = ttk.Entry(move_frame, width=5); m_fields['type'].pack(side=tk.LEFT, padx=2)
            ttk.Label(move_frame, text="威:").pack(side=tk.LEFT, padx=2) 
            m_fields['power'] = ttk.Entry(move_frame, width=3); m_fields['power'].pack(side=tk.LEFT, padx=2)
            ttk.Label(move_frame, text="型:").pack(side=tk.LEFT, padx=2) 
            m_fields['category'] = ttk.Combobox(move_frame, values=["物理", "特殊", "变化"], width=5); m_fields['category'].pack(side=tk.LEFT, padx=2)
            m_fields['category'].set("物理")
            ttk.Label(move_frame, text="命:").pack(side=tk.LEFT, padx=2) 
            m_fields['accuracy'] = ttk.Entry(move_frame, width=3); m_fields['accuracy'].pack(side=tk.LEFT, padx=2)
            ttk.Label(move_frame, text="PP:").pack(side=tk.LEFT, padx=2) 
            m_fields['pp'] = ttk.Entry(move_frame, width=3); m_fields['pp'].pack(side=tk.LEFT, padx=2)
            fields['moves_data'].append(m_fields)

        fields['moves_data'][0]['name'].insert(0, "撞击")
        fields['moves_data'][0]['type'].insert(0, "一般")
        fields['moves_data'][0]['power'].insert(0, "40")
        fields['moves_data'][0]['accuracy'].insert(0, "100")
        fields['moves_data'][0]['pp'].insert(0, "35")

        def on_submit_create():
            try:
                name = fields['name'].get().strip()
                if not name: raise ValueError("名称不能为空")
                types_list = [t.strip() for t in fields['types'].get().split(',') if t.strip()]
                if not types_list: raise ValueError("类型不能为空")
                level = int(fields['level'].get())
                if not (1 <= level <= 100): raise ValueError("等级需在1-100")
                initial_stats_dict = {}
                for key, entry in fields['initial_stats'].items():
                    initial_stats_dict[key] = int(entry.get())
                    if initial_stats_dict[key] < 1: raise ValueError(f"{key}属性值过低")
                moves = []
                for move_set_entries in fields['moves_data']:
                    m_name = move_set_entries['name'].get().strip()
                    if not m_name: continue
                    moves.append({
                        "name": m_name,
                        "type": move_set_entries['type'].get().strip() or "一般",
                        "power": int(move_set_entries['power'].get() or 0),
                        "category": move_set_entries['category'].get(),
                        "accuracy": int(move_set_entries['accuracy'].get() or 100),
                        "pp": int(move_set_entries['pp'].get() or 5)
                    })
                if not moves: moves.append({"name": "挣扎", "type": "一般", "power": 50, "category": "物理", "accuracy": 100, "pp": 1})

                new_pkm = PokemonSimplified(name, types_list, level, initial_stats=initial_stats_dict, moves_data=moves)
                success, msg = self.player.add_pokemon(new_pkm)
                messagebox.showinfo("结果", msg, parent=top)
                if success:
                    self._update_player_info_display_gui()
                    top.destroy()
            except ValueError as ve: messagebox.showerror("输入错误", str(ve), parent=top)
            except Exception as e: messagebox.showerror("创建失败", f"发生未知错误: {e}", parent=top)

        ttk.Button(top, text="确认创建", command=on_submit_create).grid(row=move_start_row + 4, columnspan=4, padx=5, pady=15)

    def _find_wild_pokemon_gui(self):
        if not self.player.get_current_pokemon():
            messagebox.showerror("错误", "你没有宝可梦或没有选定的出战宝可梦！请先创建或确保有健康的宝可梦。")
            return
        if not self.player.has_conscious_pokemon():
            messagebox.showerror("错误", "你所有宝可梦都失去战斗能力了！请先治疗。")
            return

        wild_name_parts = ["小", "野", "凶猛", "可爱", "奇怪的"]
        wild_type_choices = [["火"], ["水"], ["草"], ["电"], ["一般"], ["格斗"], ["虫"], ["飞行"], ["毒"], ["地面"]]
        opponent_name = random.choice(wild_name_parts) + "生物" + str(random.randint(1,10))
        opponent_types = random.sample(wild_type_choices, random.randint(1,2))
        opponent_types = [item for sublist in opponent_types for item in sublist] 
        player_avg_level = sum(p.level for p in self.player.pokemons) / len(self.player.pokemons) if self.player.pokemons else 3
        opponent_level = max(1, int(player_avg_level + random.randint(-2, 2)))
        opponent_initial_stats = {key: random.randint(7,11) + opponent_level//2 for key in STAT_KEYS} # Scaled initial stats
        num_moves = random.randint(1,3)
        opponent_moves = []
        for _ in range(num_moves):
            move_type = random.choice(opponent_types) if opponent_types else "一般"
            opponent_moves.append({
                "name": f"{move_type}冲击{random.randint(1,5)}", "type": move_type,
                "power": random.randint(30,70), "category": random.choice(["物理","特殊"]),
                "accuracy": random.randint(70,100), "pp": random.randint(10,25)
            })
        if not opponent_moves: opponent_moves.append({"name": "挣扎", "type": "一般", "power": 50, "category": "物理", "accuracy": 100, "pp": 1})

        self.current_opponent_obj = PokemonSimplified(
            name=opponent_name, types=opponent_types, level=opponent_level,
            initial_stats=opponent_initial_stats, moves_data=opponent_moves, is_wild=True
        )
        self.current_opponent_obj.full_heal()
        self.battle_type = "wild"
        self._start_battle_gui()

    def _start_battle_gui(self):
        self.battle_log_text.config(state=tk.NORMAL)
        self.battle_log_text.delete(1.0, tk.END)
        self.battle_log_text.config(state=tk.DISABLED)
        player_pkm = self.player.get_current_pokemon()
        if not player_pkm:
            messagebox.showerror("错误", "没有可出战的我方宝可梦！")
            return
        player_pkm.restore_pp()
        self._update_battle_labels_gui()
        self._add_battle_log_message_gui(f"野生的 {self.current_opponent_obj.name} (Lv.{self.current_opponent_obj.level}) 出现了！")
        self._add_battle_log_message_gui(f"去吧！{player_pkm.name} (Lv.{player_pkm.level})！")
        self.switch_to_battle_view_gui()
        self.proceed_button.config(state=tk.NORMAL, text="开始战斗回合")
        self.switch_pokemon_button.config(state=tk.NORMAL if len([p for p in self.player.pokemons if p.current_hp > 0 and p != player_pkm]) > 0 else tk.DISABLED)

    def _clear_and_pack_battle_buttons(self, buttons_to_pack):
        for widget in self.action_buttons_frame_battle.winfo_children():
            widget.pack_forget()
        for btn in buttons_to_pack:
            btn.pack(side=tk.LEFT, padx=10, pady=5, expand=True, fill=tk.X)

    def _process_battle_turn_gui(self):
        self.proceed_button.config(state=tk.DISABLED, text="大模型思考中...")
        self.switch_pokemon_button.config(state=tk.DISABLED)
        self.root.update_idletasks()
        player_pkm = self.player.get_current_pokemon()
        if not player_pkm or player_pkm.current_hp <= 0:
            self._add_battle_log_message_gui("我方宝可梦已无法战斗！")
            self._handle_player_pokemon_fainted_gui()
            return
        if not self.current_opponent_obj or self.current_opponent_obj.current_hp <= 0:
            self._add_battle_log_message_gui("对手宝可梦已无法战斗！战斗结束。")
            self._handle_opponent_fainted_gui()
            return

        self._add_battle_log_message_gui("\n--- 新回合 ---", delay=0)
        self._add_battle_log_message_gui("AI正在模拟战斗...", delay=0)
        
        battle_result, error = get_battle_outcome_from_llm_simplified(player_pkm, self.current_opponent_obj)

        if error:
            messagebox.showerror("API错误", f"调用大模型API失败: {error}")
            self._add_battle_log_message_gui(f"错误: {error}", delay=0)
            self.proceed_button.config(state=tk.NORMAL, text="重试回合")
            self.switch_pokemon_button.config(state=tk.NORMAL if len([p for p in self.player.pokemons if p.current_hp > 0 and p != player_pkm]) > 0 else tk.DISABLED)
            return

        self._add_battle_log_message_gui("\n--- 大模型战斗日志 ---", delay=0)
        for line in battle_result.get("battle_log", ["(大模型未提供战斗日志)"]):
            self._add_battle_log_message_gui(line)
        self._add_battle_log_message_gui("--- 战斗结算 ---", delay=0)
        player_pkm.current_hp = battle_result["pokemon1_final_hp"]
        self.current_opponent_obj.current_hp = battle_result["pokemon2_final_hp"]
        self._update_battle_labels_gui()
        winner = battle_result["winner"]
        end_messages = handle_battle_end_simplified(
            self.player, player_pkm, 
            self.current_opponent_obj.name, self.current_opponent_obj.level,
            winner, self.battle_type
        )
        for msg in end_messages: self._add_battle_log_message_gui(msg, delay=0)
        self._update_player_info_display_gui()
        if winner == "pokemon1": self._handle_opponent_fainted_gui()
        elif winner == "pokemon2": self._handle_player_pokemon_fainted_gui()
        else: 
            self._add_battle_log_message_gui("战斗平局！", delay=0)
            if player_pkm.current_hp <= 0: self._handle_player_pokemon_fainted_gui()
            elif self.current_opponent_obj.current_hp <= 0: self._handle_opponent_fainted_gui()
            else: 
                self._clear_and_pack_battle_buttons([self.proceed_button, self.switch_pokemon_button])
                self.proceed_button.config(state=tk.NORMAL, text="继续回合")
                self.switch_pokemon_button.config(state=tk.NORMAL if len([p for p in self.player.pokemons if p.current_hp > 0 and p != player_pkm]) > 0 else tk.DISABLED)

    def _handle_player_pokemon_fainted_gui(self):
        self._update_battle_labels_gui()
        if self.player.has_conscious_pokemon():
            self._add_battle_log_message_gui("请选择下一只宝可梦。", delay=0)
            self._clear_and_pack_battle_buttons([self.switch_pokemon_button]) 
            self.switch_pokemon_button.config(text="选择出战 (必须)", state=tk.NORMAL)
        else:
            self._add_battle_log_message_gui("所有宝可梦都倒下了！", delay=0)
            self._clear_and_pack_battle_buttons([]) 
            self.back_to_main_button_battle.pack(pady=10, fill=tk.X) 
        self._update_player_info_display_gui()

    def _handle_opponent_fainted_gui(self):
        self._update_battle_labels_gui()
        self._add_battle_log_message_gui(f"对手 {self.current_opponent_obj.name} 倒下了！", delay=0)
        if self.battle_type == "wild" and self.current_opponent_obj.is_wild:
            capture_btn = ttk.Button(self.action_buttons_frame_battle, text="捕捉", command=self._attempt_capture_gui)
            absorb_btn = ttk.Button(self.action_buttons_frame_battle, text="吸收", command=self._attempt_absorb_gui)
            leave_btn = ttk.Button(self.action_buttons_frame_battle, text="离开", command=self._end_battle_and_return_to_main_gui)
            self._clear_and_pack_battle_buttons([capture_btn, absorb_btn, leave_btn])
        else: 
            self._clear_and_pack_battle_buttons([])
            self.back_to_main_button_battle.pack(pady=10, fill=tk.X)
        self._update_player_info_display_gui()

    def _attempt_capture_gui(self):
        capture_message = capture_pokemon_simplified(self.player, self.current_opponent_obj)
        self._add_battle_log_message_gui(capture_message, delay=0)
        if "成功抓获" in capture_message: 
            self.current_opponent_obj.is_wild = False 
        self._clear_and_pack_battle_buttons([])
        self.back_to_main_button_battle.pack(pady=10, fill=tk.X)
        self._update_player_info_display_gui()

    def _attempt_absorb_gui(self):
        player_pkm = self.player.get_current_pokemon()
        if player_pkm:
            absorb_messages = absorb_pokemon_simplified(player_pkm, self.current_opponent_obj)
            for msg in absorb_messages: self._add_battle_log_message_gui(msg, delay=0)
            self._update_battle_labels_gui()
            self._update_player_info_display_gui()
        else:
            self._add_battle_log_message_gui("错误：没有我方宝可梦可选来吸收。", delay=0)
        self._clear_and_pack_battle_buttons([])
        self.back_to_main_button_battle.pack(pady=10, fill=tk.X)

    def _end_battle_and_return_to_main_gui(self):
        self._clear_and_pack_battle_buttons([])
        self.current_opponent_obj = None
        self.switch_to_main_view_gui()

    def _prompt_switch_pokemon_gui(self):
        player_curr_pkm = self.player.get_current_pokemon()
        must_switch = player_curr_pkm is None or player_curr_pkm.current_hp <= 0
        if must_switch: 
            healthy_options = [(i, p) for i, p in enumerate(self.player.pokemons) if p.current_hp > 0]
        else: # Optional switch
            healthy_options = [(i, p) for i, p in enumerate(self.player.pokemons) if p.current_hp > 0 and p != player_curr_pkm]
            
        if not healthy_options:
            messagebox.showinfo("提示", "没有其他可更换的健康宝可梦了。")
            if not self.player.has_conscious_pokemon(): self._handle_player_pokemon_fainted_gui() 
            return

        top = tk.Toplevel(self.root)
        top.title("选择出战宝可梦")
        top.geometry("380x300")
        top.transient(self.root)
        top.grab_set()
        ttk.Label(top, text="选择一只宝可梦:").pack(pady=10)
        listbox = tk.Listbox(top, selectmode=tk.SINGLE, exportselection=False, height=8)
        listbox.pack(pady=5, fill=tk.X, expand=True, padx=10)
        choices_map = {} 
        for list_idx, (actual_idx, pkm) in enumerate(healthy_options):
            listbox.insert(tk.END, f"{pkm.name} (Lv.{pkm.level}) HP: {pkm.current_hp}/{pkm.max_hp}")
            choices_map[list_idx] = actual_idx
        
        def on_select_switch_confirm():
            sel_indices = listbox.curselection()
            if not sel_indices:
                messagebox.showwarning("选择错误", "请选择一只宝可梦。", parent=top)
                return
            actual_player_list_idx = choices_map[sel_indices[0]]
            success, message = self.player.switch_pokemon(actual_player_list_idx)
            self._add_battle_log_message_gui(message, delay=0)
            if success:
                self._update_battle_labels_gui()
                if self.current_opponent_obj and self.current_opponent_obj.current_hp > 0:
                    self._clear_and_pack_battle_buttons([self.proceed_button, self.switch_pokemon_button])
                    self.proceed_button.config(state=tk.NORMAL, text="开始战斗回合")
                    new_player_pkm = self.player.get_current_pokemon()
                    self.switch_pokemon_button.config(state=tk.NORMAL if len([p for p in self.player.pokemons if p.current_hp > 0 and p != new_player_pkm]) > 0 else tk.DISABLED, text="更换宝可梦")
                else: 
                    self._handle_opponent_fainted_gui()
            top.destroy()
        ttk.Button(top, text="确定选择", command=on_select_switch_confirm).pack(pady=15)

    def _show_my_pokemons_gui(self):
        if not self.player.pokemons:
            messagebox.showinfo("我的宝可梦", "你还没有任何宝可梦。")
            return
        top = tk.Toplevel(self.root)
        top.title("我的宝可梦详情")
        top.geometry("600x700")
        top.transient(self.root)
        top.grab_set()
        text_widget = scrolledtext.ScrolledText(top, wrap=tk.WORD, width=70, height=35)
        text_widget.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
        info = f"训练家: {self.player.name} | 金钱: ${self.player.money}\n\n"
        for i, pkm in enumerate(self.player.pokemons):
            info += f"--- {i+1}. {pkm.name} (Lv.{pkm.level}) ---\n"
            info += f"  类型: {', '.join(pkm.types)}\n"
            info += f"  HP: {pkm.current_hp}/{pkm.max_hp} | 经验: {pkm.xp}/{pkm.next_level_xp}\n"
            info += f"  1级基础属性: {pkm._initial_stats}\n"
            info += f"  当前属性: {pkm.stats}\n"
            info += "  潜力 (1-3) [攻/防/特攻/特防/速/HP]:\n    ["
            pot_display = [f"{key.capitalize()[:2]}:{pkm.potential[key]}" for key in STAT_KEYS]
            pot_display.append(f"HP:{pkm.potential['hp']}")
            info += ", ".join(pot_display) + "]\n"
            info += "  技能 (名, 属性, 威力, 类型, 命中, PP):\n"
            if pkm.moves:
                for move in pkm.moves:
                    info += f"    - {move.name}, {move.type}, {move.power}, {move.category}, {move.accuracy}, {move.current_pp}/{move.pp}\n"
            else: info += "    (无技能)\n"
            info += "\n"
        text_widget.insert(tk.END, info)
        text_widget.config(state=tk.DISABLED)
        ttk.Button(top, text="关闭", command=top.destroy).pack(pady=10)

    def _heal_all_gui(self):
        self.player.heal_all_pokemons()
        self._update_player_info_display_gui()
        messagebox.showinfo("治疗完毕", "所有宝可梦都已完全恢复！")

# --- 主程序入口 (确保凭证检查存在) ---
if __name__ == "__main__":
    if WENXIN_APP_ID == "YOUR_APP_ID_HERE" or WENXIN_SECRET_KEY == "YOUR_SECRET_KEY_HERE":
        root_err = tk.Tk(); root_err.withdraw()
        messagebox.showerror(
            "API配置错误", 
            "文心千帆 API 凭证尚未在代码中正确配置！\n"
            "请打开此 Python 文件，\n"
            "找到 WENXIN_APP_ID 和 WENXIN_SECRET_KEY 变量，\n"
            "并用你的实际凭证替换占位符 \"YOUR_..._HERE\"。\n\n"
            "程序即将退出。"
        )
        root_err.destroy()
        exit()
    
    main_window = tk.Tk()
    app_style = ttk.Style()
    try:
        available_themes = app_style.theme_names()
        if 'clam' in available_themes: app_style.theme_use('clam')
        elif 'vista' in available_themes: app_style.theme_use('vista')
        elif 'xpnative' in available_themes: app_style.theme_use('xpnative')
    except tk.TclError:
        print("DEBUG: Preferred ttk theme not available, using default.")

    app = PokemonGameGUISimplified(main_window) # 使用上一版本中提供的GUI类名
    main_window.mainloop()